#include <arpa/inet.h>  // 主机网络字节序转化相关幻术
#include <linux/if.h>   // ifreq
#include <net/if_arp.h> // 
#include <netinet/in.h> //  sockaddr_in
#include <stdio.h>      
#include <sys/ioctl.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/if_ether.h>

#include "network_interface.h"
#include "ip_pthread.h"

int interface_num = 0;  //网卡数量
INTERFACE net_interfaces[MAX_INTERFACE_NUMS];   //接口数据



/************
 
  功能：获取网卡接口数量
  参数：无
 *************/
int get_interface_num()
{
    return interface_num;
}



/******************************************
 
  功能：扫描所有网卡接口，并获取网卡接口信息
  参数：无
 ******************************************/
void scan_all_interface()
{

    struct ifreq ifreq_arr[MAX_INTERFACE_NUMS];  // 网络接口请求地址
    struct ifconf ifc;  // 接口配置结构体， 本质上就是ifreq的封装

    // 初始化ifconf
    ifc.ifc_len = sizeof(ifreq_arr);    // 配置长度为网卡请求数组长度
    ifc.ifc_buf = (char *)ifreq_arr;    // 配置结构体的buf的地址，为请求数组的首地址

    // 获取原始套接字
    int raw_socket_fd = socket(AF_PACKET , SOCK_RAW , htons(ETH_P_ALL));
    // 获取结构列表 ， 获取成功之后， ifconf和 ifreq_arr 中的数据就有了
    if( -1 == ioctl(raw_socket_fd , SIOCGIFCONF , (char *)&ifc ) )
    {
        perror("SIOCGIFCONF ioctl");
        return ;  // 因为是调用函数，所有失败直接返回，而不是exit
    }

    // 得到接口数量
    interface_num =  ifc.ifc_len / sizeof(struct ifreq);
    // 打印一下
    printf("interface_num = %d\n", interface_num);

    // 网卡接口个数， 方便遍历
    int ifreq_num = interface_num;
    int ip; // 承接ip的32位数
    char tmp_buf[20];
    

    // 逐个遍历接口
    for(; ifreq_num >0 ;ifreq_num--)
    {
        int arr_index = ifreq_num - 1; 
        // 1. 接口名称
        // printf("if_name[%d]=%s\n",ifreq_num, ifreq_arr[ifreq_num].ifr_name);
        // 网卡名称赋值
        sprintf(net_interfaces[arr_index].if_name , "%s" , ifreq_arr[arr_index].ifr_name);
        printf("if_name[%d]=%s\n",arr_index, net_interfaces[arr_index].if_name);

        //2. 获取接口标志
        if( !(ioctl(raw_socket_fd, SIOCGIFFLAGS, (char *)&ifreq_arr[arr_index])) ){
            //接口状态
            if( ifreq_arr[arr_index].ifr_flags & IFF_UP ){
                printf("UP\n");
                net_interfaces[arr_index].flag = 1;
            }else{
                printf("DOWN\n");
                net_interfaces[arr_index].flag = 0;
            }

        }else{
            char str[256];
            sprintf(str, "SIOCGIFFLAGS ioctl %s", ifreq_arr[arr_index].ifr_name);
            perror(str);
        }

        // 3. 获取ip地址
        if( !(ioctl(raw_socket_fd, SIOCGIFADDR, (char *)&ifreq_arr[arr_index])) ){
            // 注意点： 这个使用 inet_ntop 转化成的数据是点分十进制格式的字符串， 
            printf("IP:%s\n", (char *)inet_ntoa(((struct sockaddr_in *)(&ifreq_arr[arr_index].ifr_addr) )->sin_addr ) );
            bzero( tmp_buf, sizeof(tmp_buf));
            sprintf(tmp_buf, "%s" ,(char *)inet_ntoa(((struct sockaddr_in *)(&ifreq_arr[arr_index].ifr_addr) )->sin_addr ) );

            inet_pton(AF_INET, tmp_buf , &ip);
            memcpy(net_interfaces[arr_index].if_ipaddr , &ip  ,4);
            // printf("%x%x%x%x\n" ,net_interfaces[ifreq_num].if_ipaddr[0],net_interfaces[ifreq_num].if_ipaddr[1],net_interfaces[ifreq_num].if_ipaddr[2],net_interfaces[ifreq_num].if_ipaddr[3] );
        }else{
            char str[256];
            sprintf(str, "SIOCGIFADDR ioctl %s", ifreq_arr[arr_index].ifr_name);
            perror(str);
        }

        // 4. 子网掩码
         if( !(ioctl(raw_socket_fd, SIOCGIFNETMASK, (char *)&ifreq_arr[arr_index])) ){
            // 注意点： 这个使用 inet_ntop 转化成的数据是点分十进制格式的字符串， 
            printf("netmask:%s\n", (char *)inet_ntoa(((struct sockaddr_in *)(&ifreq_arr[arr_index].ifr_netmask) )->sin_addr ) );
            bzero( tmp_buf, sizeof(tmp_buf)); // 重置字符数组
            sprintf(tmp_buf, "%s" ,(char *)inet_ntoa(((struct sockaddr_in *)(&ifreq_arr[arr_index].ifr_addr) )->sin_addr ) );

            inet_pton(AF_INET, tmp_buf , &ip);
            memcpy(net_interfaces[arr_index].if_netmask , &ip  ,4);
            // printf("%x%x%x%x\n" ,net_interfaces[arr_index].if_ipaddr[0],net_interfaces[arr_index].if_ipaddr[1],net_interfaces[ifreq_num].if_ipaddr[2],net_interfaces[ifreq_num].if_ipaddr[3] );
        }else{
            char str[256];
            sprintf(str, "SIOCGIFNETMASK ioctl %s", ifreq_arr[arr_index].ifr_name);
            perror(str);
        }

        // 5. 广播地址
        if( !(ioctl(raw_socket_fd, SIOCGIFBRDADDR, (char *)&ifreq_arr[arr_index])) ){
            // 注意点： 这个使用 inet_ntop 转化成的数据是点分十进制格式的字符串， 
            printf("broadaddr:%s\n", (char *)inet_ntoa(((struct sockaddr_in *)(&ifreq_arr[arr_index].ifr_broadaddr) )->sin_addr ) );
            bzero( tmp_buf, sizeof(tmp_buf)); // 重置字符数组
            sprintf(tmp_buf, "%s" ,(char *)inet_ntoa(((struct sockaddr_in *)(&ifreq_arr[arr_index].ifr_broadaddr) )->sin_addr ) );

            inet_pton(AF_INET, tmp_buf , &ip);
            memcpy(net_interfaces[arr_index].if_brd_ip , &ip  ,4);
            // printf("%x%x%x%x\n" ,net_interfaces[arr_index].if_ipaddr[0],net_interfaces[ifreq_num].if_ipaddr[1],net_interfaces[ifreq_num].if_ipaddr[2],net_interfaces[ifreq_num].if_ipaddr[3] );
        }else{
            char str[256];
            sprintf(str, "SIOCGIFBRDADDR ioctl %s", ifreq_arr[arr_index].ifr_name);
            perror(str);
        }

        //  6. mac地址
        if( !(ioctl(raw_socket_fd, SIOCGIFHWADDR, (char *)&ifreq_arr[arr_index])) ){
           printf("%02x:%02x:%02x:%02x:%02x:%02x\n", (unsigned char )(ifreq_arr[arr_index].ifr_hwaddr.sa_data[0]),
           (unsigned char )(ifreq_arr[arr_index].ifr_hwaddr.sa_data[1]),
           (unsigned char )(ifreq_arr[arr_index].ifr_hwaddr.sa_data[2]) ,
           (unsigned char )(ifreq_arr[arr_index].ifr_hwaddr.sa_data[3]) ,
           (unsigned char )(ifreq_arr[arr_index].ifr_hwaddr.sa_data[4]) ,
           (unsigned char )(ifreq_arr[arr_index].ifr_hwaddr.sa_data[5])     );

           memcpy(net_interfaces[arr_index].if_hwaddr , (unsigned char* )(ifreq_arr[arr_index].ifr_hwaddr.sa_data) , 6 );

        }else{
            char str[256];
            sprintf(str, "SIOCGIFHWADDR ioctl %s", ifreq_arr[arr_index].ifr_name);
            perror(str);
        }
        


    }

    close(raw_socket_fd);

}




/******************************************************************
函	数:	int find_network_segment_bydstip(unsigned char *ip)
功	能:	根据目的ip查找对应网段
参	数:	unsigned char *ip 目的IP
返回值: 网段编号
*******************************************************************/
int find_network_segment_bydstip( char* ip)
{
    
    int i=0;
    for( i = 0; i < interface_num; i++)
    {
        
        // 比较目的ip和所有网卡接口的ip的网段, 
        if( memcmp(ip , net_interfaces[i].if_ipaddr , netmask_char_num ) == 0 ) 
        {
            break;
        }

    }
    
    // 返回网卡信息数组下标
    return i;

}
